package org.hxyjs.shiro.filter;


import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.hxyjs.dto.DTO;
import org.hxyjs.entity.Account;
import org.hxyjs.exception.NoPermissionExecption;
import org.hxyjs.service.AccountService;
import org.hxyjs.utils.ContextUtils;
import org.springframework.context.annotation.Lazy;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.PrintWriter;
import java.util.Optional;

public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {
    @Resource
	@Lazy
	AccountService accountService;
	@Override
	protected boolean onAccessDenied(ServletRequest req, ServletResponse res) throws Exception {
		// 在这里进行验证码的校验
		HttpServletRequest request = (HttpServletRequest) req;
		HttpSession session = request.getSession();
		res.setCharacterEncoding("utf-8");
		req.setCharacterEncoding("utf-8");
		res.setContentType("text/html; charset=utf-8");


//		// 取出验证码
//		String validateCode = (String) session.getAttribute("validateCode");
//		// 取出页面的验证码
//		// 输入的验证和session中的验证进行对比
//		String randomcode = httpServletRequest.getParameter("randomcode");
//		if (randomcode != null && validateCode != null && !randomcode.equals(validateCode)) {
//			// 如果校验失败，将验证码错误失败信息，通过shiroLoginFailure设置到request中
//			httpServletRequest.setAttribute("shiroLoginFailure", "randomCodeError");
//			// 拒绝访问，不再校验账号和密码
//			return true;
//		}


		//解决通过remeberMe 登录 session 无效问题

		Subject subject = SecurityUtils.getSubject();//subject是单例 所以通过工具类获得是同一个

		System.out.println( request.getRequestURI());
		if( request.getRequestURI().equals("/favicon.ico")){
			return true;
		}
		System.out.println("认证");
		//不是认证通过,就需要根据认证中的账号 作为认证登录，只能访问 user的资源 不能访问authc的资源
		// 当前没有登录 但登录对象中有记住我 再次查询权限登录
		System.out.println(request.getParameterMap().keySet().size());

		String names[] =	ContextUtils.getSpringMVCContext().getBeanDefinitionNames();
		Session shiroSession = subject.getSession();
		Object modelNameInSession = shiroSession.getAttribute("modelName");
		//默认从session 取 如果session中没有从request取
		String modelName = null;

        org.springframework.beans.factory.config.PropertyPathFactoryBean tt = null;
		try {
			System.out.println( request.getParameter("modelName"));
			modelName =
					Optional.ofNullable(modelNameInSession).isPresent() ? modelNameInSession.toString() : request.getParameter("modelName").toString();//从session 也是同一个（shiro包装了基本的httpSession 浏览器不换就是同一个）
			System.out.println(modelName + " 000066666");
			shiroSession.setAttribute("modelName", modelName);
		}catch (NullPointerException e){
			//e.printStackTrace();
			System.out.println("非法操作null");
			res.setCharacterEncoding("utf-8");
			PrintWriter out = res.getWriter();
			DTO dto = new DTO(302, "非法操作","login");
			out.print(new ObjectMapper().writeValueAsString(dto));
			out.flush();
			out.close();
			throw new NoPermissionExecption("没有权限非法操作");
			//return false;
		}
//要走到认证2 需要满足 没有登录  有记住我  通过session 没有用户，额外存了一个标志 用户在没有登录的情况可以访问user对应的资源
		if(!subject.isAuthenticated()&&subject.isRemembered()&&session.getAttribute("user")==null){
			System.out.println("认证2");

			Object principal = subject.getPrincipal();//和getUsername的区别是 一个得对象一个得字符串
			if(principal != null){
				System.out.println("认证3");

				accountService = (AccountService) ContextUtils.getSpringMVCContext().getBean(modelName+"Service");
				String accountname = principal.toString();
				Account account = accountService.getAccountByAccountName(accountname).getT();
				System.out.println();
				System.out.println(account);
				shiroSession.setAttribute("user", account);
			}
		}




		return super.onAccessDenied(request, res);
	}
}
